package edu.manju.mimi.lord;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

/**
 * <h4>mimi-lord-server</h4>
 * <p>Onenet的Token生成示例</p>
 * 参见[OneNET开发文档](https://open.iot.10086.cn/doc/mq/book/develop-manual/auth.html)
 *
 * @author : Lebei(lebei163@163.com)
 * @date : 2023-03-04 09:38
 **/
public class OnenetTokenGenerator {
    public static String assembleToken(String version,
                                       String resourceName,
                                       String expirationTime,
                                       String signatureMethod,
                                       String accessKey)
            throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
        StringBuilder sb = new StringBuilder();
        String res = URLEncoder.encode(resourceName, StandardCharsets.UTF_8);
        String sig = generatorSignature(version, resourceName, expirationTime, accessKey, signatureMethod);
        String sigEncode = URLEncoder.encode(sig, StandardCharsets.UTF_8);
        sb.append("version=").append(version)
                .append("&res=").append(res)
                .append("&et=").append(expirationTime)
                .append("&method=").append(signatureMethod)
                .append("&sign=").append(sigEncode);
        return sb.toString();
    }

    public static String generatorSignature(
            String version,
            String resourceName,
            String expirationTime,
            String accessKey,
            String signatureMethod) throws NoSuchAlgorithmException, InvalidKeyException {
        String encryptText = expirationTime + "\n"
                + signatureMethod + "\n"
                + resourceName + "\n" + version;
        byte[] bytes = HmacEncrypt(encryptText, accessKey, signatureMethod);
        String signature = Base64.getEncoder().encodeToString(bytes);
        return signature;
    }

    public static byte[] HmacEncrypt(
            String data,
            String base64Key,
            String signatureMethod) throws NoSuchAlgorithmException, InvalidKeyException {
        String algorithm = "Hmac" + signatureMethod.toUpperCase();
        byte[] keyBytes = Base64.getDecoder().decode(base64Key);

        //根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
        SecretKeySpec signingKey = new SecretKeySpec(keyBytes, algorithm);

        //生成一个指定Mac算法的Mac对象
        Mac mac = Mac.getInstance(algorithm);

        //用给定密钥初始化Mac对象
        mac.init(signingKey);

        //完成Mac操作
        return mac.doFinal(data.getBytes());
    }

    public enum SignatureMethod {
        SHA1, MD5, SHA256
    }

    public static void main(String[] args) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
        String version = "2018-10-31";
        String resourceName = "products/spEbjokOkY/devices/00000004-00000013";
//        String expirationTime = System.currentTimeMillis() / 1000 + 3600 + "";
        String expirationTime = "1682303894";
        System.out.println("expirationTime: " + expirationTime);
        String signatureMethod = SignatureMethod.SHA1.name().toLowerCase();
        String accessKey = "GPSBVSbV71WcFtf14X6Tl7EKe9dcJTiYCAwk8P3emus=";
        String token = assembleToken(version, resourceName, expirationTime, signatureMethod, accessKey);
        System.out.println("Authorization:" + token);
        System.out.println("Current Time: " + System.currentTimeMillis());
    }
}
